package com.yzcrm.erp.psi.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.aop.Inject;
import com.jfinal.core.Controller;
import com.jfinal.core.paragetter.Para;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.Record;
import com.yzcrm.common.annotation.Permissions;
import com.yzcrm.erp.psi.service.PsiReportService;
import com.yzcrm.swagger.annotation.ActionApi;
import com.yzcrm.swagger.annotation.Api;
import com.yzcrm.swagger.annotation.Param;
import com.yzcrm.swagger.annotation.Params;
import com.yzcrm.utils.R;
import org.apache.poi.ss.usermodel.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author jiang.xue
 * 出入库报表
 */
@Api(remark = "进销存：出入库报表")
public class PsiReportController extends Controller{

    @Inject
    private PsiReportService psiReportService;

    /**
     * @author jiang.xue
     * 出入库报表(销售)
     */
    @ActionApi(summary = "出入库报表(销售)", remark="出入库报表(销售)")
    @Params({
            @Param(name="startDate", remark="开始日期", dataType="String", defaultValue="", required=false),
            @Param(name="endDate", remark="结束日期", dataType="String", defaultValue="", required=false),
            @Param(name="productName", remark="产品名称", dataType="String", defaultValue="", required=false),
            @Param(name="productNameEn", remark="产品英文名称", dataType="String", defaultValue="", required=false),
            @Param(name="productSpecName", remark="产品规格", dataType="String", defaultValue="", required=false),
            @Param(name="storehouseId", remark="仓库Id", dataType="Int", defaultValue="", required=false),
            @Param(name="customerName", remark="使用人（客户名称）", dataType="String", defaultValue="", required=false),
            @Param(name="productUpcCode", remark="产品序列号", dataType="String", defaultValue="", required=false),
            @Param(name="elsNum", remark="出入库编号", dataType="String", defaultValue="", required=false),
            @Param(name="labels", remark="功能标签，20销售退货 21归还入库 22维修入库等。多个使用逗号分割，如：20,45,46", dataType="String", defaultValue="", required=false),
            @Param(name="page", remark="页码", dataType="Int", defaultValue="", required=true),
            @Param(name="limit", remark="每页数量", dataType="Int", defaultValue="", required=true),
            @Param(name="sortColumns", remark="排序列 如: els_num asc, label desc ", dataType="String", defaultValue="", required=false)
    })
    @Permissions({"psi:elsSalesmanReport:index"})
    public void queryElsSalesmanReport(
                          @Para("startDate") String startDate,
                          @Para("endDate") String endDate,
                          @Para("productName") String productName,
                          @Para("productNameEn") String productNameEn,
                          @Para("productSpecName") String productSpecName,
                          @Para("storehouseId") String storehouseId,
                          @Para("customerName") String customerName,
                          @Para("productUpcCode") String productUpcCode,
                          @Para("labels") String labels,
                          @Para("elsNum") String elsNum,
                          @Para("page") Integer page,
                          @Para("limit") Integer limit,
                          @Para("sortColumns") String sortColumns) {
        renderJson(psiReportService.queryElsReport(startDate,endDate,productName,productNameEn,productSpecName,
                storehouseId,customerName,productUpcCode,labels,elsNum,page,limit,sortColumns, "salesman"));
    }

    @ActionApi(summary = "出入库报表(销售)导出", remark="出入库报表(销售)导出")
    @Params({
            @Param(name="startDate", remark="开始日期", dataType="String", defaultValue="", required=false),
            @Param(name="endDate", remark="结束日期", dataType="String", defaultValue="", required=false),
            @Param(name="productName", remark="产品名称", dataType="String", defaultValue="", required=false),
            @Param(name="productNameEn", remark="产品英文名称", dataType="String", defaultValue="", required=false),
            @Param(name="productSpecName", remark="产品规格", dataType="String", defaultValue="", required=false),
            @Param(name="storehouseId", remark="仓库Id", dataType="Int", defaultValue="", required=false),
            @Param(name="customerName", remark="使用人（客户名称）", dataType="String", defaultValue="", required=false),
            @Param(name="productUpcCode", remark="产品序列号", dataType="String", defaultValue="", required=false),
            @Param(name="elsNum", remark="出入库编号", dataType="String", defaultValue="", required=false),
            @Param(name="labels", remark="功能标签，20销售退货 21归还入库 22维修入库等。多个使用逗号分割，如：20,45,46", dataType="String", defaultValue="", required=false),
            @Param(name="sortColumns", remark="排序列 如: els_num asc, label desc ", dataType="String", defaultValue="", required=false)
    })
    @Permissions({"psi:elsSalesmanReport:export"})
    public void elsSalesmanReportExport(
            @Para("startDate") String startDate,
            @Para("endDate") String endDate,
            @Para("productName") String productName,
            @Para("productNameEn") String productNameEn,
            @Para("productSpecName") String productSpecName,
            @Para("storehouseId") String storehouseId,
            @Para("customerName") String customerName,
            @Para("productUpcCode") String productUpcCode,
            @Para("labels") String labels,
            @Para("elsNum") String elsNum,
            @Para("sortColumns") String sortColumns) {

        JSONObject resultData = (JSONObject)psiReportService.queryElsReport(startDate,endDate,productName,productNameEn,productSpecName,
                storehouseId,customerName,productUpcCode,labels,elsNum,null,null,sortColumns, "salesman").get("data");

        List<Record> recordList = resultData.getJSONArray("list").toJavaList(Record.class);
        export(recordList, "salesman");
        renderNull();
    }

    /**
     * 出入库报表(销售)
     */
    @ActionApi(summary = "出入库报表(销售) 表头", remark="出入库报表(销售) 表头")
    public void queryElsSalesmanReportListHead() {

        renderJson(R.ok().put("data", psiReportService.queryElsReportListHead("salesman")));
    }



    /**
     * @author jiang.xue
     * 出入库报表(采购)
     */
    @ActionApi(summary = "出入库报表(采购)", remark="出入库报表(采购)")
    @Params({
            @Param(name="startDate", remark="开始日期", dataType="String", defaultValue="", required=false),
            @Param(name="endDate", remark="结束日期", dataType="String", defaultValue="", required=false),
            @Param(name="productName", remark="产品名称", dataType="String", defaultValue="", required=false),
            @Param(name="productNameEn", remark="产品英文名称", dataType="String", defaultValue="", required=false),
            @Param(name="productSpecName", remark="产品规格", dataType="String", defaultValue="", required=false),
            @Param(name="storehouseId", remark="仓库Id", dataType="Int", defaultValue="", required=false),
            @Param(name="customerName", remark="使用人（客户名称）", dataType="String", defaultValue="", required=false),
            @Param(name="productUpcCode", remark="产品序列号", dataType="String", defaultValue="", required=false),
            @Param(name="elsNum", remark="出入库编号", dataType="String", defaultValue="", required=false),
            @Param(name="labels", remark="功能标签，20销售退货 21归还入库 22维修入库等。多个使用逗号分割，如：20,45,46", dataType="String", defaultValue="", required=false),
            @Param(name="page", remark="页码", dataType="Int", defaultValue="", required=true),
            @Param(name="limit", remark="每页数量", dataType="Int", defaultValue="", required=true),
            @Param(name="sortColumns", remark="排序列 如: els_num asc, label desc ", dataType="String", defaultValue="", required=false)
    })
    @Permissions({"psi:elsPurchaserReport:index"})
    public void queryElsPurchaserReport(
            @Para("startDate") String startDate,
            @Para("endDate") String endDate,
            @Para("productName") String productName,
            @Para("productNameEn") String productNameEn,
            @Para("productSpecName") String productSpecName,
            @Para("storehouseId") String storehouseId,
            @Para("customerName") String customerName,
            @Para("productUpcCode") String productUpcCode,
            @Para("labels") String labels,
            @Para("elsNum") String elsNum,
            @Para("page") Integer page,
            @Para("limit") Integer limit,
            @Para("sortColumns") String sortColumns) {
        renderJson(psiReportService.queryElsReport(startDate,endDate,productName,productNameEn,productSpecName,
                storehouseId,customerName,productUpcCode,labels,elsNum,page,limit,sortColumns, "purchaser"));
    }

    @ActionApi(summary = "出入库报表(采购)导出", remark="出入库报表(采购)导出")
    @Params({
            @Param(name="startDate", remark="开始日期", dataType="String", defaultValue="", required=false),
            @Param(name="endDate", remark="结束日期", dataType="String", defaultValue="", required=false),
            @Param(name="productName", remark="产品名称", dataType="String", defaultValue="", required=false),
            @Param(name="productNameEn", remark="产品英文名称", dataType="String", defaultValue="", required=false),
            @Param(name="productSpecName", remark="产品规格", dataType="String", defaultValue="", required=false),
            @Param(name="storehouseId", remark="仓库Id", dataType="Int", defaultValue="", required=false),
            @Param(name="customerName", remark="使用人（客户名称）", dataType="String", defaultValue="", required=false),
            @Param(name="productUpcCode", remark="产品序列号", dataType="String", defaultValue="", required=false),
            @Param(name="elsNum", remark="出入库编号", dataType="String", defaultValue="", required=false),
            @Param(name="labels", remark="功能标签，20销售退货 21归还入库 22维修入库等。多个使用逗号分割，如：20,45,46", dataType="String", defaultValue="", required=false),
            @Param(name="sortColumns", remark="排序列 如: els_num asc, label desc ", dataType="String", defaultValue="", required=false)
    })
    @Permissions({"psi:elsPurchaserReport:export"})
    public void elsPurchaserReportExport(
            @Para("startDate") String startDate,
            @Para("endDate") String endDate,
            @Para("productName") String productName,
            @Para("productNameEn") String productNameEn,
            @Para("productSpecName") String productSpecName,
            @Para("storehouseId") String storehouseId,
            @Para("customerName") String customerName,
            @Para("productUpcCode") String productUpcCode,
            @Para("labels") String labels,
            @Para("elsNum") String elsNum,
            @Para("sortColumns") String sortColumns) {

        JSONObject resultData = (JSONObject)psiReportService.queryElsReport(startDate,endDate,productName,productNameEn,productSpecName,
                storehouseId,customerName,productUpcCode,labels,elsNum,null,null,sortColumns, "purchaser").get("data");

        List<Record> recordList = resultData.getJSONArray("list").toJavaList(Record.class);
        export(recordList, "purchaser");
        renderNull();
    }

    /**
     * 出入库报表(采购)
     */
    @ActionApi(summary = "出入库报表(采购) 表头", remark="出入库报表(采购) 表头")
    public void queryElsPurchaserReportListHead() {

        renderJson(R.ok().put("data", psiReportService.queryElsReportListHead("purchaser")));
    }




    /**
     * @author jiang.xue
     * 出入库报表(总监)
     */
    @ActionApi(summary = "出入库报表(总监)", remark="出入库报表(总监)")
    @Params({
            @Param(name="startDate", remark="开始日期", dataType="String", defaultValue="", required=false),
            @Param(name="endDate", remark="结束日期", dataType="String", defaultValue="", required=false),
            @Param(name="productName", remark="产品名称", dataType="String", defaultValue="", required=false),
            @Param(name="productNameEn", remark="产品英文名称", dataType="String", defaultValue="", required=false),
            @Param(name="productSpecName", remark="产品规格", dataType="String", defaultValue="", required=false),
            @Param(name="storehouseId", remark="仓库Id", dataType="Int", defaultValue="", required=false),
            @Param(name="customerName", remark="使用人（客户名称）", dataType="String", defaultValue="", required=false),
            @Param(name="productUpcCode", remark="产品序列号", dataType="String", defaultValue="", required=false),
            @Param(name="elsNum", remark="出入库编号", dataType="String", defaultValue="", required=false),
            @Param(name="labels", remark="功能标签，20销售退货 21归还入库 22维修入库等。多个使用逗号分割，如：20,45,46", dataType="String", defaultValue="", required=false),
            @Param(name="page", remark="页码", dataType="Int", defaultValue="", required=true),
            @Param(name="limit", remark="每页数量", dataType="Int", defaultValue="", required=true),
            @Param(name="sortColumns", remark="排序列 如: els_num asc, label desc ", dataType="String", defaultValue="", required=false)
    })
    @Permissions({"psi:elsDirectorReport:index"})
    public void queryElsDirectorReport(
            @Para("startDate") String startDate,
            @Para("endDate") String endDate,
            @Para("productName") String productName,
            @Para("productNameEn") String productNameEn,
            @Para("productSpecName") String productSpecName,
            @Para("storehouseId") String storehouseId,
            @Para("customerName") String customerName,
            @Para("productUpcCode") String productUpcCode,
            @Para("labels") String labels,
            @Para("elsNum") String elsNum,
            @Para("page") Integer page,
            @Para("limit") Integer limit,
            @Para("sortColumns") String sortColumns) {
        renderJson(psiReportService.queryElsReport(startDate,endDate,productName,productNameEn,productSpecName,
                storehouseId,customerName,productUpcCode,labels,elsNum,page,limit,sortColumns, "director"));
    }

    @ActionApi(summary = "出入库报表(总监)导出", remark="出入库报表(总监)导出")
    @Params({
            @Param(name="startDate", remark="开始日期", dataType="String", defaultValue="", required=false),
            @Param(name="endDate", remark="结束日期", dataType="String", defaultValue="", required=false),
            @Param(name="productName", remark="产品名称", dataType="String", defaultValue="", required=false),
            @Param(name="productNameEn", remark="产品英文名称", dataType="String", defaultValue="", required=false),
            @Param(name="productSpecName", remark="产品规格", dataType="String", defaultValue="", required=false),
            @Param(name="storehouseId", remark="仓库Id", dataType="Int", defaultValue="", required=false),
            @Param(name="customerName", remark="使用人（客户名称）", dataType="String", defaultValue="", required=false),
            @Param(name="productUpcCode", remark="产品序列号", dataType="String", defaultValue="", required=false),
            @Param(name="elsNum", remark="出入库编号", dataType="String", defaultValue="", required=false),
            @Param(name="labels", remark="功能标签，20销售退货 21归还入库 22维修入库等。多个使用逗号分割，如：20,45,46", dataType="String", defaultValue="", required=false),
            @Param(name="sortColumns", remark="排序列 如: els_num asc, label desc ", dataType="String", defaultValue="", required=false)
    })
    @Permissions({"psi:elsDirectorReport:export"})
    public void elsDirectorReportExport(
            @Para("startDate") String startDate,
            @Para("endDate") String endDate,
            @Para("productName") String productName,
            @Para("productNameEn") String productNameEn,
            @Para("productSpecName") String productSpecName,
            @Para("storehouseId") String storehouseId,
            @Para("customerName") String customerName,
            @Para("productUpcCode") String productUpcCode,
            @Para("labels") String labels,
            @Para("elsNum") String elsNum,
            @Para("sortColumns") String sortColumns) {

        JSONObject resultData = (JSONObject)psiReportService.queryElsReport(startDate,endDate,productName,productNameEn,productSpecName,
                storehouseId,customerName,productUpcCode,labels,elsNum,null,null,sortColumns, "director").get("data");

        List<Record> recordList = resultData.getJSONArray("list").toJavaList(Record.class);
        export(recordList, "director");
        renderNull();
    }

    /**
     * 出入库报表(总监)
     */
    @ActionApi(summary = "出入库报表(总监) 表头", remark="出入库报表(总监) 表头")
    public void queryElsDirectorReportListHead() {

        renderJson(R.ok().put("data", psiReportService.queryElsReportListHead("director")));
    }




    /**
     * @author jiang.xue
     * 出入库报表(无价格)
     */
    @ActionApi(summary = "出入库报表(无价格)", remark="出入库报表(无价格)")
    @Params({
            @Param(name="startDate", remark="开始日期", dataType="String", defaultValue="", required=false),
            @Param(name="endDate", remark="结束日期", dataType="String", defaultValue="", required=false),
            @Param(name="productName", remark="产品名称", dataType="String", defaultValue="", required=false),
            @Param(name="productNameEn", remark="产品英文名称", dataType="String", defaultValue="", required=false),
            @Param(name="productSpecName", remark="产品规格", dataType="String", defaultValue="", required=false),
            @Param(name="storehouseId", remark="仓库Id", dataType="Int", defaultValue="", required=false),
            @Param(name="customerName", remark="使用人（客户名称）", dataType="String", defaultValue="", required=false),
            @Param(name="productUpcCode", remark="产品序列号", dataType="String", defaultValue="", required=false),
            @Param(name="elsNum", remark="出入库编号", dataType="String", defaultValue="", required=false),
            @Param(name="labels", remark="功能标签，20销售退货 21归还入库 22维修入库等。多个使用逗号分割，如：20,45,46", dataType="String", defaultValue="", required=false),
            @Param(name="page", remark="页码", dataType="Int", defaultValue="", required=true),
            @Param(name="limit", remark="每页数量", dataType="Int", defaultValue="", required=true),
            @Param(name="sortColumns", remark="排序列 如: els_num asc, label desc ", dataType="String", defaultValue="", required=false)
    })
    @Permissions({"psi:elsNoPriceReport:index"})
    public void queryElsNoPriceReport(
            @Para("startDate") String startDate,
            @Para("endDate") String endDate,
            @Para("productName") String productName,
            @Para("productNameEn") String productNameEn,
            @Para("productSpecName") String productSpecName,
            @Para("storehouseId") String storehouseId,
            @Para("customerName") String customerName,
            @Para("productUpcCode") String productUpcCode,
            @Para("labels") String labels,
            @Para("elsNum") String elsNum,
            @Para("page") Integer page,
            @Para("limit") Integer limit,
            @Para("sortColumns") String sortColumns) {
        renderJson(psiReportService.queryElsReport(startDate,endDate,productName,productNameEn,productSpecName,
                storehouseId,customerName,productUpcCode,labels,elsNum,page,limit,sortColumns, "NoPrice"));
    }

    @ActionApi(summary = "出入库报表(无价格)导出", remark="出入库报表(无价格)导出")
    @Params({
            @Param(name="startDate", remark="开始日期", dataType="String", defaultValue="", required=false),
            @Param(name="endDate", remark="结束日期", dataType="String", defaultValue="", required=false),
            @Param(name="productName", remark="产品名称", dataType="String", defaultValue="", required=false),
            @Param(name="productNameEn", remark="产品英文名称", dataType="String", defaultValue="", required=false),
            @Param(name="productSpecName", remark="产品规格", dataType="String", defaultValue="", required=false),
            @Param(name="storehouseId", remark="仓库Id", dataType="Int", defaultValue="", required=false),
            @Param(name="customerName", remark="使用人（客户名称）", dataType="String", defaultValue="", required=false),
            @Param(name="productUpcCode", remark="产品序列号", dataType="String", defaultValue="", required=false),
            @Param(name="elsNum", remark="出入库编号", dataType="String", defaultValue="", required=false),
            @Param(name="labels", remark="功能标签，20销售退货 21归还入库 22维修入库等。多个使用逗号分割，如：20,45,46", dataType="String", defaultValue="", required=false),
            @Param(name="sortColumns", remark="排序列 如: els_num asc, label desc ", dataType="String", defaultValue="", required=false)
    })
    @Permissions({"psi:elsNoPriceReport:export"})
    public void elsNoPriceReportExport(
            @Para("startDate") String startDate,
            @Para("endDate") String endDate,
            @Para("productName") String productName,
            @Para("productNameEn") String productNameEn,
            @Para("productSpecName") String productSpecName,
            @Para("storehouseId") String storehouseId,
            @Para("customerName") String customerName,
            @Para("productUpcCode") String productUpcCode,
            @Para("labels") String labels,
            @Para("elsNum") String elsNum,
            @Para("sortColumns") String sortColumns) {

        JSONObject resultData = (JSONObject)psiReportService.queryElsReport(startDate,endDate,productName,productNameEn,productSpecName,
                storehouseId,customerName,productUpcCode,labels,elsNum,null,null,sortColumns, "NoPrice").get("data");

        List<Record> recordList = resultData.getJSONArray("list").toJavaList(Record.class);
        export(recordList, "NoPrice");
        renderNull();
    }

    /**
     * 出入库报表(无价格)
     */
    @ActionApi(summary = "出入库报表(无价格) 表头", remark="出入库报表(无价格) 表头")
    public void queryElsNoPriceReportListHead() {

        renderJson(R.ok().put("data", psiReportService.queryElsReportListHead("NoPrice")));
    }


    private void export(List<Record> recordList, String priceType) {
        try (ExcelWriter writer = ExcelUtil.getWriter()) {

            List<Record> headList = psiReportService.queryElsReportListHead(priceType);

            headList.forEach(head -> writer.addHeaderAlias(StrUtil.toUnderlineCase(head.getStr("fieldName")), head.getStr("name")));

            HttpServletResponse response = getResponse();
            List<Map<String, Object>> list = new ArrayList<>();
            if (recordList.size() == 0) {
                Record record = new Record();
                headList.forEach(head -> record.set(StrUtil.toUnderlineCase(head.getStr("fieldName")), ""));
                list.add(record.getColumns());
            }
            recordList.forEach(record -> list.add(record.getColumns()));
            writer.setOnlyAlias(true);
            writer.write(list, true);
            writer.setRowHeight(0, 20);
            writer.setRowHeight(1, 20);
            for (int i = 0; i < headList.size(); i++) {
                writer.setColumnWidth(i, 20);
            }
            Cell cell = writer.getCell(0, 0);
            CellStyle cellStyle = cell.getCellStyle();
            cellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            Font font = writer.createFont();
            font.setBold(true);
            font.setFontHeightInPoints((short) 16);
            cellStyle.setFont(font);
            cell.setCellStyle(cellStyle);
            //自定义标题别名
            //response为HttpServletResponse对象
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setCharacterEncoding("UTF-8");
            //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
            response.setHeader("Content-Disposition", "attachment;filename=psi.xls");
            ServletOutputStream out = response.getOutputStream();
            writer.flush(out);
        } catch (Exception e) {
            Log.getLog(getClass()).error("导出出入库报表错误：", e);
        }
    }

}
